package com.cskaoyan.javase.oop3.abstract1.introduction1;

/**
 * @description: 引入抽象类
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * Animal类的继承体系，有什么问题？
 * - 从代码角度上，有没有冗余代码？
 * Animal类中shout方法我们至始至终没有调用过，这个方法只是用来被继承然后重写，理想情况下，我们希望这个方法没有方法体，只有声明。这个方法就纯粹是用来重写的
 * - 从设计角度上，在这个案例中，会存在一个“动物”对象吗？
 *  内存中只存在Animal的引用，不存在一个Animal对象
 *  这个类我们不是用来创建对象的，而是用来被继承的
 *  我们只需要拿到它的子类对象就可以了
 *
 *  所以，Animal在本案例中已经上升到了一个抽象的概念，它只是用来被继承的。而且对于一个抽象的概念，你不能描述它的行为
 *  总结：
 *  所以说从这个角度shout()方法的方法体也是多余的，并且Animal不应该能够创建对象
 *  去掉一个方法的方法体后，程序立刻报错
 *  Missing method body, or declare abstract
 *  一个方法要么是有方法体的，要么声明为abstract抽象
 *  如何声明一个abstract方法
 *  语法：
 *  [访问权限修饰符] abstract 返回值类型 方法名();
 *  分号不要忘记了
 *  把方法声明为abstract后，程序又报错了
 *  Class 'Animal' must either be declared abstract or implement abstract method 'shout()' in 'Animal'
 *  一个类要么声明为abstract，要么就必须实现所有的抽象方法
 *  重要：abstract方法必须在一个抽象类中
 * 怎么声明一个抽象类？
 * [访问权限修饰符] abstract class 类名{
 * }
 * 抽象类无法创建对象
 */
public class Demo {
    public static void main(String[] args) {
        //创建Animal对象
        //'Animal' is abstract; cannot be instantiated 抽象类无法实例化，无法创建对象
        //Animal a = new Animal();

        //验证多态性
        //抽象类也是类，和多态调用没有本质区别
        Animal a;
        a = new Cat();
        a.shout();
        a = new Dog();
        a.shout();
    }
}
abstract class Animal {
    public abstract void shout();//'{' or ';' expected
}
class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}
class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}